#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <csignal>
#include <cstring>
#include<ctime>
using namespace std;

void printpending(sigset_t *set)
{
    for (int i = 32; i >= 1; i--)
    {
        if (i % 4 == 0) cout << " ";
        if (sigismember(set, i)) cout << 1;
        else cout << 0;
    }
    cout << endl;
}

//问题一：sigaction是如何使用的？
//问题二：pending位图，什么时候从1->0,执行信号捕捉方法之前，先清零，再调用？
//问题三：信号被处理的时候，对应的信号也会被添加到block表中，防止信号捕捉被嵌套调用
//问题四：volatile关键字的作用是什么？

void handler(int singo)
{
    cout << "Signal " << singo << " received." << endl;
    while(1)
    {
        sigset_t pending;
        sigemptyset(&pending); // 初始化挂起信号集为空
        sigpending(&pending); // 获取当前进程的挂起信号集
        printpending(&pending); // 打印挂起信号集
        // cout << "Running... Press Ctrl+C to send SIGINT." << endl;
        sleep(1);
    }
}


void test1()
{
    struct sigaction act,oact;
    //进行一下初始化
    memset(&act, 0, sizeof(act));
    memset(&oact, 0, sizeof(oact));
    act.sa_handler= handler; // 设置信号处理函数为handler
    sigset_t set;
    sigemptyset(&set); // 初始化信号集为空
    sigaddset(&set, 3); //ctrl/加入
    act.sa_mask = set; // 设置阻塞信号集为set
    int n=sigaction(2,&act,&oact); // 设置SIGINT信号的处理函数为handler，并保存之前的处理函数到oact中

    while(1)
    {
        sigset_t pending;
        sigemptyset(&pending); // 初始化挂起信号集为空
        sigpending(&pending); // 获取当前进程的挂起信号集
        printpending(&pending); // 打印挂起信号集
        // cout << "Running... Press Ctrl+C to send SIGINT." << endl;
        sleep(1);
    }
}

volatile int flag=0;

void Handler(int sig)
{
    cout << "Signal " << sig << " received." << endl;
    flag = 1; // 设置标志位为1，表示信号已处理
    // 这里可以添加其他处理逻辑
}
void test2()
{
    signal(SIGINT,Handler);
    while(!flag);
    cout<< "test2: finish" << endl;
}

void handlersig(int sig)
{
    cout << "Signal " << sig << " received." << endl;
    // 这里可以添加其他处理逻辑
    pid_t pid;
    while((pid = waitpid(-1, nullptr, WNOHANG)) > 0) // 非阻塞轮询回收子进程,用一个信号可以回收同时多个子进程
    {
        cout << "Child process " << pid << " terminated." << endl;
    }
}

void test3()
{
    srand((unsigned int)time(nullptr)); // 初始化随机数种子
    signal(SIGCHLD, handlersig); // 捕捉SIGCHLD信号
    // signal(SIGCHLD, SIG_IGN); // 忽略SIGCHLD信号,直接回收子进程，无需等待
    for(int i=0;i<10;i++)
    {
        sleep(rand()%5+3);
        pid_t pid = fork(); // 创建子进程
        if (pid < 0)
        {
            perror("fork");
            return;
        }
        else if (pid == 0) // 子进程
        {
            sleep(2); // 模拟子进程工作
            exit(0); // 子进程结束
        }
        else // 父进程
        {
            cout << "Parent process finished waiting for child." << endl;
        }
    }
}

int main()
{

    test3();
    return 0;
}